/*******************************************************************************
 * @note Copyright (C) 2011-2022, Shanghai Panchip Microelectronics Co., Ltd. 
 * @SPDX-License-Identifier: Apache-2.0
 * @history - V0.1, 2022-09-28
*******************************************************************************/
#include "ds18b20.h"


/*******************************************************************************
* 函 数 名         : DS18B20_IO_IN
* 函数功能		   : DS18B20_IO输入配置	   
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void DS18B20_IO_IN(void)
{
	SetBit(((uint32_t)&M0P_GPIO->PADIR + GpioPortA), GpioPin8,  1u);
}

/*******************************************************************************
* 函 数 名         : DS18B20_IO_OUT
* 函数功能		   : DS18B20_IO输出配置	   
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void DS18B20_IO_OUT(void)
{
	SetBit(((uint32_t)&M0P_GPIO->PADIR + GpioPortA), GpioPin8,  0u);
}

/*******************************************************************************
* 函 数 名         : DS18B20_Reset
* 函数功能		   : 复位DS18B20  
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void DS18B20_Reset(void)	   
{                 
	DS18B20_IO_OUT(); 		//SET PG11 OUTPUT
	DS18B20_DQ_OUT_CLR(); 	//拉低DQ
	delay_us(1000);    		//拉低750us
	DS18B20_DQ_OUT_SET() ; 	//DQ=1 
	delay_us(15);     		//15US
}

/*******************************************************************************
* 函 数 名         : DS18B20_Check
* 函数功能		   : 检测DS18B20是否存在
* 输    入         : 无
* 输    出         : 1:未检测到DS18B20的存在，0:存在
*******************************************************************************/
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();	
	
	while ( DS18B20_DQ_IN() &&retry<200)
	{
		retry++;
		delay_us(1);

	};
	
	if(retry>=200)
		return 1;
	else 
		retry=0;
	
	while (!DS18B20_DQ_IN() &&retry<240)
	{
		retry++;
		delay_us(1);

	};
	
	if(retry>=240)
	{
		return 1;	
	}		
	
	return 0;
}

/*******************************************************************************
* 函 数 名         : DS18B20_Read_Bit
* 函数功能		   : 从DS18B20读取一个位
* 输    入         : 无
* 输    出         : 1/0
*******************************************************************************/
u8 DS18B20_Read_Bit(void) 			 // read one bit
{
	u8 data;
	DS18B20_IO_OUT();//SET PG11 OUTPUT
	DS18B20_DQ_OUT_CLR();
	delay_us(2);
	DS18B20_DQ_OUT_SET() ; 
	DS18B20_IO_IN();//SET PG11 INPUT
	delay_us(12);
	
	if(DS18B20_DQ_IN() )
		data=1;
	else 
		data=0;	 
	
	delay_us(50);  
	
	return data;
}

/*******************************************************************************
* 函 数 名         : DS18B20_Read_Byte
* 函数功能		   : 从DS18B20读取一个字节
* 输    入         : 无
* 输    出         : 一个字节数据
*******************************************************************************/
u8 DS18B20_Read_Byte(void)    // read one byte
{        
	u8 i,j,dat;
	dat=0;
	for (i=1;i<=8;i++) 
	{
		j=DS18B20_Read_Bit();
		dat=(j<<7)|(dat>>1);
	}						    
	return dat;
}

/*******************************************************************************
* 函 数 名         : DS18B20_Write_Byte
* 函数功能		   : 写一个字节到DS18B20
* 输    入         : dat：要写入的字节
* 输    出         : 无
*******************************************************************************/
void DS18B20_Write_Byte(u8 dat)     
{             
	u8 j;
	u8 testb;
	DS18B20_IO_OUT();		//SET PG11 OUTPUT;
	for (j=1;j<=8;j++) 
	{
		testb=dat&0x01;
		dat=dat>>1;
		if (testb) 
		{
			DS18B20_DQ_OUT_CLR(); // Write 1
			delay_us(2);                            
			DS18B20_DQ_OUT_SET() ;
			delay_us(60);             
		}
		else 
		{
			DS18B20_DQ_OUT_CLR(); // Write 0
			delay_us(60);             
			DS18B20_DQ_OUT_SET() ;
			delay_us(2);                          
		}
	}
}

/*******************************************************************************
* 函 数 名         : DS18B20_Start
* 函数功能		   : 开始温度转换
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void DS18B20_Start(void)// ds1820 start convert
{   						               
	DS18B20_Reset();	   
	DS18B20_Check();	 
	DS18B20_Write_Byte(0xcc);// skip rom
	DS18B20_Write_Byte(0x44);// convert 
} 
 

/*******************************************************************************
* 函 数 名         : DS18B20_Init
* 函数功能		   : 初始化DS18B20的IO口 DQ 同时检测DS的存在
* 输    入         : 无
* 输    出         : 1:不存在，0:存在
*******************************************************************************/    	 
u8 DS18B20_Init(void)
{
	stc_gpio_cfg_t stcGpioCfg;
	
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 
	
    stcGpioCfg.enPu = GpioPuDisable;                       
    stcGpioCfg.enPd = GpioPdDisable;
    stcGpioCfg.enOD = GpioOdDisable;                       
    stcGpioCfg.enCtrlMode = GpioAHB;                 

	Gpio_Init(DS18B20_PORT, DS18B20_PIN, &stcGpioCfg);
 
 	DS18B20_Reset();
	return DS18B20_Check();
}   

/*******************************************************************************
* 函 数 名         : DS18B20_GetTemperture
* 函数功能		   : 从ds18b20得到温度值
* 输    入         : 无
* 输    出         : 温度数据
*******************************************************************************/ 
float DS18B20_GetTemperture(void)
{
	u16 temp;
	u8 a,b;
	float value;
	
	DS18B20_Start();                 // ds1820 start convert
	DS18B20_Reset();
	DS18B20_Check();	 
	DS18B20_Write_Byte(0xcc);		// skip rom 
	DS18B20_Write_Byte(0xbe);		// convert
	a=DS18B20_Read_Byte(); 			// LSB   
	b=DS18B20_Read_Byte();			// MSB   
	temp=b;
	temp=(temp<<8)+a;
	
	if((temp&0xf800)==0xf800)
	{
		temp=(~temp)+1;
		value=temp*(-0.0625);
	}
	else
	{
		value=temp*0.0625;	
	}
	return value;    
}
